home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / irit / rend386 / polyblit / f3dkitn.c next >
Encoding:
C/C++ Source or Header  |  1992-12-06  |  9.7 KB  |  447 lines

  1. #include <bios.h>
  2. #include <dos.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6. unsigned int dpaddr = 0;        /* video write base */
  7.  
  8. unsigned long l_hold, r_hold;          /* used to hold old x data for edge */
  9.  
  10. int l_clip = 0;         /* clipping rectangle for polys and lines */
  11. int r_clip = 319;       /* max. 0,319,0,199              */
  12. int t_clip = 0;
  13. int b_clip = 199;
  14.  
  15. typedef struct lp {           /* set of points for clipping or line dwg */
  16.             int x1, y1, x2, y2;
  17.           } lpoints;
  18.  
  19.  
  20.  
  21.  
  22. extern void far vsync();                /* pause till vert. retrace */
  23. extern void far vga_reg(int reg);     /* load VGA register:  */
  24.                     /* reg = reg# + 256*value */
  25.  
  26. extern void far load_color(int color);  /* load VGA color register */
  27. extern void far set_vmode(int mode);    /* set video mode thru BIOS */
  28. extern void far set_vpage(int page);    /* set video page thru BIOS */
  29.  
  30.  
  31. #define PUT 0        /* defines of VGA write modes */
  32. #define AND 1           /* for use with setup_hdwe()  */
  33. #define OR  2
  34. #define XOR 3
  35.  
  36. extern void far setup_hdwe(int mode);  /* setup VGA for bunch of line */
  37.                        /* or poly draws: once per set */
  38.  
  39. extern void far reset_hdwe();  /* reset VGA to BIOS state after drawing */
  40.  
  41.              /* clear video page to solid color: 10 mS */
  42.              /* returns -1 if bad page #         */
  43. extern int far clr_page(int page, int color);
  44.  
  45.             /* copy one page to another for use as */
  46.             /* background: 21 mS per call          */
  47.             /* returns -1 if bad page #            */
  48. extern int far copy_page(int source, int dest);
  49.  
  50.             /* fast VGA line draw: about 15600 24-pixel */
  51.             /* vectors/sec (horizontal much faster)     */
  52. extern void far vgaline(int x1, int y1, int x2, int y2, int color);
  53.  
  54.             /* line draw using lpoint structure   */
  55. void vgalines(lpoints *points, int color);
  56.  
  57.             /* Fast Cohen-Sutherland line clipper */
  58.             /* modifies data in points, returns   */
  59.             /* 0 if not clipped, 1 if clipped,    */
  60.             /* -1 if undrawable                   */
  61.             /* 2 - 10 uS per call                 */
  62. int clipper (lpoints far *points);
  63.  
  64.             /* does C-S clipping and draws line   */
  65.             /* returns same codes as C-S clipper  */
  66. int clipline (lpoints *points, int color);
  67.  
  68. #define NO_HOLD  0      /* values for hold in tpoly() */
  69. #define L_HOLD   1
  70. #define R_HOLD   2
  71. #define HOLD_ALL 3
  72. #define HOLD 0x8000     /* use in x1 or x2 to continue poly side */
  73.  
  74.             /* draws trapeziodal poly slice FAST   */
  75.             /* x1 is top left, x2 is top right,    */
  76.             /* y1 is top, y3 is bottom.  Clipping  */
  77.             /* is performed.  l_incr and r_incr    */
  78.             /* set slope of sides.               */
  79.             /* if x1 or x2 = HOLD, continues that  */
  80.             /* side from last tpoly call.  Use     */
  81.             /* bits in hold to ensure that needed  */
  82.             /* side data is good in previous tpoly */
  83. extern int far tpoly(int x1,int x2, long l_incr, long r_incr,
  84.                              int y1, int y3);
  85.  
  86.                    /* compute (x1-x2)/(y1-y2) << 16 */
  87.                    /* used for tpoly...             */
  88.                    /* returns x1-x2 if y1==y2       */
  89. extern long far compute_slope(int x1, int x2, int y1, int y2);
  90.  
  91. void set_gmode();              /* enters 320x200x16 mode, clears screen */
  92. void restore_gmode();          /* enters 320x200x16 mode w/o  clearing screen */
  93. void exit_gmode();             /* exits to text mode */
  94.  
  95. int set_drawpage(int page);        /* set page for drawing on (0-7)   */
  96.  
  97.              /* set displayed page: uses BIOS   */
  98.              /* call, so DON'T use in interrupt */
  99.              /* routines! If WAIT is 1, will    */
  100.              /* sync with vert. retrace (pause) */
  101. int set_vidpage(int page, int wait);
  102.  
  103.  
  104.                    /* draw and fill 3-sided polygon    */
  105.                    /* 5800 polys/sec for 24x24         */
  106. poly3(int x1, int y1, int x2, int y2, int x3, int y3, int color);
  107.  
  108.                 /* N-sided poly fill (unclipped)    */
  109.                 /* 3800 30x30 polys/sec             */
  110.                 /* args: ptr to x and y arrays      */
  111. polyn(int *xp, int *yp, int count, int color);
  112.  
  113.  
  114.  
  115. /************* GRAPHICS MODE CONTROL SUPPORT **************/
  116.  
  117. void set_gmode()        /* enters 320x200x16 mode, clears screen */
  118. {
  119.  set_vmode(0x0D);
  120. }
  121.  
  122.  
  123. void restore_gmode()        /* enters 320x200x16 mode w/o  clearing screen */
  124. {
  125.  set_vmode(0x8D);
  126. }
  127.  
  128.  
  129. void exit_gmode()        /* exits to text mode */
  130. {
  131.  set_vmode(0x02);
  132. }
  133.  
  134.  
  135. int set_drawpage(int page)      /* set page for drawing */
  136. {
  137.  if(page>7) return(-1);
  138.  dpaddr = 8192*page;
  139.  return(0);
  140. }
  141.  
  142.  
  143. int set_vidpage(int page, int wait)  /* set visible page, wait for vsync */
  144. {
  145.  if(page>7) return(-1);
  146.  set_vpage(page);
  147.  if(wait) vsync();
  148. }
  149.  
  150.  
  151. /******************* LINE DRAWING SUPPORT ***************/
  152.  
  153. void vgalines(lpoints *l, int color)
  154. {
  155.  vgaline(l->x1, l->y1, l->x2, l->y2, color);
  156. }
  157.  
  158.  
  159. int clipline(lpoints *l, int color)
  160. {
  161.  register int i;
  162.  
  163.  if ((i=clipper(l))==-1) return(i);
  164.  vgaline(l->x1, l->y1, l->x2, l->y2, color);
  165.  return(i);
  166. }
  167.  
  168.  
  169.  
  170. /*************** 3-SIDED POLYGON DRAW AND FILL ***************/
  171.  
  172. poly3(int x1, int y1, int x2, int y2, int x3, int y3, int color)
  173. {
  174.  register int i;
  175.  long s12, s23, s13;
  176.  
  177.  if(y2<y1)       /* sort by vert pos'n */
  178.   {
  179.    i = y1;
  180.    y1 = y2;
  181.    y2 = i;
  182.    i = x1;
  183.    x1 = x2;
  184.    x2 = i;
  185.   }
  186.  
  187.  if(y3<y1)
  188.   {
  189.    i = y1;
  190.    y1 = y3;
  191.    y3 = i;
  192.    i = x1;
  193.    x1 = x3;
  194.    x3 = i;
  195.   }
  196.  
  197.  if(y3<y2)
  198.   {
  199.    i = y2;
  200.    y2 = y3;
  201.    y3 = i;
  202.    i = x2;
  203.    x2 = x3;
  204.    x3 = i;
  205.   }
  206.  
  207.  if(y1==y2&&y2==y3) return;
  208.  
  209.  load_color(color);
  210.  
  211.  if(y1==y2)        /* case = 2 (flat top) */
  212.   {
  213.    if(x2<x1)
  214.     {
  215.      i = x1;
  216.      x1 = x2;
  217.      x2 = i;
  218.     }
  219.    s23 = compute_slope(x2,y2,x3,y3);
  220.    s13 = compute_slope(x1,y1,x3,y3);
  221.    tpoly(x1,x2,s13,s23,y1,y3);
  222.   }
  223.  else if(y2==y3)     /* case = 1 (flat bottom)*/
  224.   {
  225.    if(x3<x2)
  226.     {
  227.      i = x2;            /* sort bottom sides */
  228.      x2 = x3;
  229.      x3 = i;
  230.     }
  231.    s12 = compute_slope(x1,y1,x2,y2);
  232.    s13 = compute_slope(x1,y1,x3,y3);
  233.    tpoly(x1,x1,s12,s13,y1,y3);
  234.   }
  235.  else
  236.   {
  237.    s12 = compute_slope(x1,y1,x2,y2);
  238.    s23 = compute_slope(x2,y2,x3,y3);
  239.    s13 = compute_slope(x1,y1,x3,y3);
  240.  
  241.    if(s12>s13)     /* case = 4 (3rd point on right) */
  242.     {
  243.      tpoly(x1,x1,s13,s12,y1,y2);
  244.      tpoly(0x8000,x2,s13,s23,y2,y3);
  245.     }
  246.    else         /* case = 3 (3rd point on left)  */
  247.     {
  248.      tpoly(x1,x1,s12,s13,y1,y2);
  249.      tpoly(x2,0x8000,s23,s13,y2,y3);
  250.     }
  251.   }
  252. }
  253.  
  254.  
  255.  
  256. /******************* N-SIDED CONVEX POLY DRAW AND FILL **************/
  257.  
  258. /* draw n sided poly-- MUST BE CONVEX   */
  259. /* max. 20 vertices: must be preclipped */
  260. /* ABSOLUTELY NO CLIPPING ! */
  261.  
  262.  
  263.  
  264. #define WSIZE 60          /* number of entries in array */
  265. #define YTOX WSIZE              /* offset from Y to X data    */
  266. int work[WSIZE+WSIZE];        /* left, right point lists */
  267.                 /* y first, then x */
  268.  
  269. polyn(int*xp, int *yp, int count, int color)
  270.                 /* does multisided convex polys      */
  271. {                               /* by "walking" left and right edges */
  272.  register int i;
  273.  int j,y;
  274.  
  275.  int top,bot;
  276.  int tlx,tly,trx,try;
  277.  int blx,bly,brx,bry;
  278.  
  279.  long sl,sr;
  280.  
  281.  int *ls;
  282.  int *rs;
  283.  int *w;
  284.  
  285.  if(count<2) return;
  286.  if(count==3)                 /* do 3-sided poly if possible */
  287.   {
  288.    poly3(*xp,*yp,*(xp+1),*(yp+1),*(xp+2),*(yp+2),color);
  289.    return;
  290.   }
  291.  
  292.  if(count > WSIZE/3)return;            /* 3 copies of data needed */
  293.  
  294.  memcpy(&work[0],yp,sizeof(int)*count);
  295.  memcpy(&work[YTOX],xp,sizeof(int)*count);
  296.  memcpy(&work[count],yp,sizeof(int)*count);
  297.  memcpy(&work[YTOX+count],xp,sizeof(int)*count);
  298.  memcpy(&work[count+count],yp,sizeof(int)*count);
  299.  memcpy(&work[YTOX+count+count],xp,sizeof(int)*count);
  300.  
  301.  y = 1000;
  302.  w = &work[0];
  303.  for(i=0;i<count;i++)         /* find topmost, leftmost point */
  304.   {
  305.    if(*w <= y)
  306.     {
  307.      ls = w;
  308.      y = *w;
  309.      j = i;
  310.     }
  311.    w++;
  312.   }
  313.  if(j==count-1 && work[0] == y)    /* need to continue search for left? */
  314.   {
  315.    w = ls+1;
  316.    for(i=0;;i++)
  317.     {
  318.      if(i==count)return;
  319.      if(*w == y) ls = w++;
  320.      else break;
  321.     }
  322.    ls -= count;     /* put back in buffer start */
  323.   }
  324.  
  325.  w = ls+1;
  326.  while(1)           /* find topmost, rightmost point */
  327.   {
  328.    if(*w == y)
  329.     {
  330.      rs = w;
  331.      break;
  332.     }
  333.    w++;
  334.   }
  335.  rs += count;
  336.  
  337.  y = *ls;               /* find end of left points */
  338.  w = ls+1;
  339.  while(1)
  340.   {
  341.    if(*w < y)
  342.     {
  343.      *w = -1;
  344.      break;
  345.     }
  346.    y = *w++;
  347.   }
  348.  
  349.  y = *rs;               /* find end of right points */
  350.  w = rs-1;
  351.  while(1)
  352.   {
  353.    if(*w < y)
  354.     {
  355.      *w = -1;
  356.      break;
  357.     }
  358.    y = *w--;
  359.   }
  360.  
  361.  load_color(color);
  362.  
  363. bothnew:                   /* top set of points */
  364.  tly = *ls;
  365.  tlx = *(ls+YTOX);
  366.  trx = *(rs+YTOX);
  367.  try = *rs;
  368.  
  369.  bly = *(ls+1);                     /* bottom set of points */
  370.  blx = *(ls+YTOX+1);
  371.  brx = *(rs+YTOX-1);
  372.  bry = *(rs-1);
  373.  
  374.  if(bly==-1 || bry == -1)return;
  375.  
  376.  top = tly;
  377.  bot = (bry<bly) ? bry : bly ;
  378.  
  379.  sl = compute_slope(tlx,tly,blx,bly);   /* draw first trapezoid */
  380.  sr = compute_slope(trx,try,brx,bry);
  381.  tpoly(tlx,trx,sl,sr,top,bot);
  382.  
  383. next_slice:
  384.  if(bly==bry)        /* both edges ended */
  385.   {
  386.    ls++;                                /* next left */
  387.    if(*ls==-1) return;
  388.    while(*ls==*(ls+1)) ls++;   /* skip duplicates */
  389.    if(*ls==-1) return;
  390.  
  391.    rs--;                                /* next left */
  392.    if(*rs==-1) return;
  393.    while(*rs==*(rs-1)) rs--;   /* skip duplicates */
  394.    if(*rs==-1) return;
  395.  
  396.    goto bothnew;
  397.   }
  398.  
  399.  if(bot==bry)           /* right edge ended */
  400.   {
  401.    rs--;                     /* next right */
  402.    if(*rs==-1) return;
  403.    while(*rs==*(rs-1)) rs--;   /* skip duplicates */
  404.    if(*rs==-1) return;
  405.  
  406.    trx = *(rs+YTOX);
  407.    try = *rs;
  408.  
  409.    brx = *(rs+YTOX-1);
  410.    bry = *(rs-1);
  411.  
  412.    if(bry == -1)return;
  413.  
  414.    top = try;
  415.    bot = (bry<bly) ? bry : bly ;
  416.  
  417.    sr = compute_slope(trx,try,brx,bry);
  418.    tpoly(0x8000,trx,sl,sr,top,bot);
  419.    goto next_slice;
  420.   }
  421.  
  422.  else            /* left edge ended  */
  423.   {
  424.    ls++;                     /* next left */
  425.    if(*ls==-1) return;
  426.    while(*ls==*(ls+1)) ls++;   /* skip duplicates */
  427.    if(*ls==-1) return;
  428.  
  429.    tly = *ls;
  430.    tlx = *(ls+YTOX);
  431.  
  432.    bly = *(ls+1);                     /* bottom set of points */
  433.    blx = *(ls+YTOX+1);
  434.    if(bly == -1)return;
  435.  
  436.    top = tly;
  437.    bot = (bry<bly) ? bry : bly ;
  438.  
  439.    sl = compute_slope(tlx,tly,blx,bly);
  440.    tpoly(tlx,0x8000,sl,sr,top,bot);
  441.    goto next_slice;
  442.   }
  443. }
  444.  
  445.  
  446.  
  447.